package as2.model.pojo;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyColumn;
import javax.persistence.Table;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

@Entity
@Table(name = "orders")
public class Order {
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "order_id")
	Long orderId = null;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "user_id", nullable = false)
	User user;

	@Column(name = "address_city")
	String addressCity;

	@Column(name = "shipping_cost")
	double shippingCost = 0.0;

	@Column(name = "order_time")
	Date orderTime = new Date();

	@Column(name = "item_cost")
	double itemCost = 0.0;

	@Enumerated(EnumType.STRING)
	@Column(name = "status")
	OrderStatus status = OrderStatus.PROCESSING;

	/** (item_id : quantity) mapping */
	@ElementCollection(fetch = FetchType.EAGER)
	@CollectionTable(name = "order_lines", joinColumns = @JoinColumn(name = "order_id"))
	@MapKeyColumn(name = "item_id")
	@Column(name = "quantity")
	Map<String, Integer> orderLines = new HashMap<String, Integer>();

	public Order() {
	}

	public Order(User user) {
		this.user = user;
	}

	public void addItems(String itemId, int quantity) {
		if (orderLines.containsKey(itemId)) {
			quantity += orderLines.get(itemId);
		}
		orderLines.put(itemId, quantity);
	}

	public void removeItems(String itemId, int quantity) {
		if (orderLines.containsKey(itemId)) {
			quantity = orderLines.get(itemId) - quantity;
		}
		if (quantity <= 0) {
			orderLines.remove(itemId);
		} else {
			orderLines.put(itemId, quantity);
		}
	}

	public void removeItems(String itemId) {
		orderLines.remove(itemId);
	}

	public Long getOrderId() {
		return orderId;
	}

	/**
	 * DO NOT manually set this, leave it at null for auto-increment
	 * 
	 * @param orderId
	 */
	@Deprecated
	public void setOrderId(Long orderId) {
		this.orderId = orderId;
	}

	public User getUser() {
		return null;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public String getAddressCity() {
		return addressCity;
	}

	public void setAddressCity(String addressCity) {
		this.addressCity = addressCity;
	}

	public double getTotalCost() {
		return itemCost + shippingCost;
	}

	public double getShippingCost() {
		return shippingCost;
	}

	public void setShippingCost(double shippingCost) {
		this.shippingCost = shippingCost;
	}

	public Date getOrderTime() {
		return orderTime;
	}

	public void setOrderTime(Date orderTime) {
		this.orderTime = orderTime;
	}

	public void setOrderTime() {
		this.orderTime = new Date();
	}

	public String getStatus() {
		return status.toString();
	}

	public void setStatus(OrderStatus status) {
		this.status = status;
	}

	public JSONArray getOrderLines() throws JSONException {
		JSONArray lines = new JSONArray();
		JSONObject item;
		for (String key : orderLines.keySet()) {
			item = new JSONObject();
			item.put("item_id", key);
			item.put("quantity", orderLines.get(key));
			lines.put(item);
		}

		return lines;
	}

	public void setOrderLines(Map<String, Integer> orderLines) {
		this.orderLines = orderLines;
	}

	public double getItemCost() {
		return itemCost;
	}

	public void setItemCost(double itemCost) {
		this.itemCost = itemCost;
	}

	public String toString() {
		return "id:" + orderId + " user:" + user.userId + " city:"
				+ addressCity + " status:" + status + orderLines;
	}
}
